home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
falcon
/
programm.ing
/
nt_dsp1.lzh
/
NT_DSP1.MSA
/
FFT
/
DCT1.ASM
next >
Wrap
Assembly Source File
|
1990-01-17
|
6KB
|
149 lines
;
; This program, originally available on the Motorola DSP bulletin board,
; is provided under a DISCLAIMER OF WARRANTY available from Motorola DSP
; Operation, 6501 William Cannon Drive, West, Austin, Texas 78735-8598.
;
ident 1,1
page 132,56,1,1
opt mex,nomd,cex
;
; Discrete Cosine Transform (DCT)
;
; V1.2
; 03 Oct 88
;
; The DCT is implemented by using the method described in
; "On the Computation of the Discrete Cosine Transform", IEEE
; Transactions on Communications. Vol COM-26, No. 6, June 1978
;
; The operation of this transform is as follows:
; 1. Resort the original sequence.
; 2. Perform an FFT on the modified sequence.
; 3. Multiply the output of the FFT by a complex exponential
; and take the real part.
; 4. Perform a bit reversed sort to unscramble the result.
;
; After the transform, the data needs to be scaled (according to
; the previously cited reference):
; g(0) = g(0)*1.414/N
; g(k) = g(k)*2.0/N k=1,2,...,N-1
; This scaling is NOT performed by this program. This type of scaling
; is application dependent and some implementations may not require
; the scaling.
;
include 'sincos'
include 'fftr2aa'
start equ $100 ;beginning of program in P memory
points equ 16 ;number of points in dct
data equ 0 ;address of data in Y memory
coef equ 16 ;address of coefficients
sincos points,coef ;generate twiddle factor for FFT.
; Generate exponential table after twiddle factor table.
;
; This generates the scale factor of EXP(-j*pi*k/(2*N)).
; The real part is in Y memory and the imaginary part is
; in X memory. Note that the negative of the part in Y memory
; is actually stored so that a -1 (exactly) can be represented
; with the fractional arithmetic. This negative sign is
; compensated when the actual rotation is performed.
;
rot equ pi/@cvf(2*points)
org x:
exptbl
count set 0
dup points
dc -@sin(@cvf(count)*rot)
count set count+1
endm
org y:
count set 0
dup points
dc -@cos(@cvf(count)*rot)
count set count+1
endm
org p:start
;
; Do inital sort. The input data is in Y, the sorted data goes to X.
; This forms a new sequence in X memory from the sequence in Y memory
; according to the definition:
; x(k)=y(2k)
; x(N-1-K)=x(2k+1) k=0,1,...,N/2-1
;
move #$ffff,m0 ;set linear
move m0,m4 ;ditto
move #data,r0 ;point to data
move #2,n0 ;jump by even numbers
move r0,r4 ;copy data pointer
move y:(r0)+n0,a ;get first point
rep #points/2 ;sort even points
move y:(r0)+n0,a a,x:(r4)+
move #data+1,r0 ;point to odds
move #data+points-1,r4 ;odds output
move y:(r0)+n0,a ;get first odd
rep #points/2 ;sort odd points
move y:(r0)+n0,a a,x:(r4)-
clr a #data,r0 ;get a zero, point r0 to data
rep #points ;clear out original data
move a,y:(r0)+
;
; Do an FFT on the new sequence
;
fftr2aa points,data,coef ;do FFT
;
; Multiply the output by a complex exponential and take the
; real part. dct=re[ (a+jb)*(c+jd)] = a*c-b*d where a+jb is the
; output of the FFT and c+jd is the rotation factor. Note that
; the data is still in bit reversed order but the rotation
; table is in sequential order. Thus, the data is accessed with
; bit reversed addressing but the rotation table is addressed
; with linear addressing.
;
move #exptbl,r0 ;point to exponential table
move #$ffff,m0 ;linear addressing
move #data,r4 ;point to output of fft
move r4,r5 ;copy data pointer
move #0,m4 ;bit reversed addressing
move m4,m5
move #points/2,n4
move n4,n5
move x:(r4),x0 y:(r0),y0 ;get a,-c
do #points,_gf ;do all points
mpy -x0,y0,a x:(r0)+,x1 y:(r4)+n4,y1 ;-a*c, get d,b
macr -x1,y1,a x:(r4),x0 y:(r0),y0 ;-b*d, get a,c
move a,x:(r5)+n5 ;save dct
_gf
;
; Bit reverse the output. The rotated and bit reversed data from X
; memory is transfered to Y memory and unscrambled. The resulting
; DCT is in Y memory starting at DATA with length POINTS.
;
move #data,r0 ;point to data
move #points/2,n0 ;number of points/2
move #0,m0 ;set reverse carry
move r0,r4 ;copy pointer
move #$ffff,m4 ;set linear
move x:(r0)+n0,a ;do preload
rep #points ;unscramble
move x:(r0)+n0,a a,y:(r4)+
end
^Z